#include "stdafx.h"
#include "ProfilerCallback.h"
#include "ClassFactory.h"
#include "RegUtil.h"

HINSTANCE g_hInst; 

BOOL APIENTRY DllMain( HINSTANCE hModule,
					  DWORD  ul_reason_for_call,
					  LPVOID lpReserved
					  )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		g_hInst = hModule;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

STDAPI DllUnregisterServer();

// {60753780-9324-450B-9D29-EEE959735F66}
static const GUID CLSID_PROFILER = { 0x60753780, 0x9324, 0x450b, { 0x9d, 0x29, 0xee, 0xe9, 0x59, 0x73, 0x5f, 0x66 } };

#define PROFILER_GUID "{60753780-9324-450B-9D29-EEE959735F66}"

const COCLASS_REGISTER g_CoClasses[] =
{   
	&CLSID_PROFILER,
	PROFILER_GUID,          
	ProfilerCallback::CreateObject,
	NULL,               
	NULL,               
	NULL
};

STDAPI DllRegisterServer()
{    
	HRESULT hr = S_OK;
	char  rcModule[_MAX_PATH];  
	const COCLASS_REGISTER *pCoClass;   

	DllUnregisterServer();
	GetModuleFileNameA(g_hInst, rcModule, NumItems( rcModule ) );

	// for each item in the coclass list, register it
	for ( pCoClass = g_CoClasses; (SUCCEEDED( hr ) && (pCoClass->pClsid != NULL)); pCoClass++ )
	{
		// register the class with default values
		hr = RegUtil::RegisterCOMClass( *pCoClass->pClsid, 
			"My Profiler", 
			"My Profiler",
			1, 
			pCoClass->szProgID, 
			"Both", 
			rcModule );                 
	}

	if ( FAILED( hr ) )
		DllUnregisterServer();

	return hr; 
}

STDAPI DllUnregisterServer()
{    
	const COCLASS_REGISTER *pCoClass;   

	// for each item in the coclass list, unregister it
	for ( pCoClass = g_CoClasses; pCoClass->pClsid != NULL; pCoClass++ )
	{
		RegUtil::UnregisterCOMClass( *pCoClass->pClsid, 
			"My Profiler",
			1, 
			pCoClass->szProgID );
	}

	return S_OK;  
}

STDAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv )                  
{    
	CClassFactory *pClassFactory;       
	const COCLASS_REGISTER *pCoClass;   
	HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;

	// scan for the right one
	for ( pCoClass = g_CoClasses; pCoClass->pClsid != NULL; pCoClass++ )
	{
		if ( *pCoClass->pClsid == rclsid )
		{
			pClassFactory = new CClassFactory( pCoClass );
			if ( pClassFactory != NULL )
			{   
				hr = pClassFactory->QueryInterface( riid, ppv );

				pClassFactory->Release();
				break;
			}
			else
			{
				hr = E_OUTOFMEMORY;
				break;    
			}
		}
	}

	return hr;
}